using System;
using System.Collections.Generic;
using System.Linq;
using WenYu.Core.Errors;

namespace WenYu.Core.CodeGen;

/// <summary>
/// 标准库函数注册表 - 管理所有标准库函数的元数据
/// 为动态标准库系统提供基础
/// </summary>
public class StandardLibraryRegistry
{
    private readonly Dictionary<string, StandardLibraryFunctionInfo> _functions = new();
    
    /// <summary>
    /// 注册标准库函数
    /// </summary>
    public void RegisterFunction(StandardLibraryFunctionInfo funcInfo)
    {
        if (_functions.ContainsKey(funcInfo.Name))
        {
            throw new InvalidOperationException($"标准库函数 '{funcInfo.Name}' 已注册");
        }
        
        _functions[funcInfo.Name] = funcInfo;
    }
    
    /// <summary>
    /// 批量注册函数
    /// </summary>
    public void RegisterFunctions(IEnumerable<StandardLibraryFunctionInfo> functions)
    {
        foreach (var func in functions)
        {
            RegisterFunction(func);
        }
    }
    
    /// <summary>
    /// 检查函数是否已注册
    /// </summary>
    public bool HasFunction(string name)
    {
        return _functions.ContainsKey(name);
    }
    
    /// <summary>
    /// 获取函数信息
    /// </summary>
    public StandardLibraryFunctionInfo GetFunction(string name)
    {
        if (!_functions.TryGetValue(name, out var funcInfo))
        {
            throw new InvalidOperationException($"未注册的标准库函数: {name}");
        }
        return funcInfo;
    }
    
    /// <summary>
    /// 尝试获取函数信息
    /// </summary>
    public bool TryGetFunction(string name, out StandardLibraryFunctionInfo? funcInfo)
    {
        return _functions.TryGetValue(name, out funcInfo);
    }
    
    /// <summary>
    /// 获取所有已注册的函数
    /// </summary>
    public IEnumerable<StandardLibraryFunctionInfo> GetAllFunctions()
    {
        return _functions.Values;
    }
    
    /// <summary>
    /// 获取指定分类的函数
    /// </summary>
    public IEnumerable<StandardLibraryFunctionInfo> GetFunctionsByCategory(string category)
    {
        return _functions.Values.Where(f => f.Category == category);
    }
    
    /// <summary>
    /// 验证函数调用参数
    /// </summary>
    public bool ValidateArguments(string funcName, int argCount, out string? errorMessage)
    {
        errorMessage = null;
        
        if (!TryGetFunction(funcName, out var funcInfo) || funcInfo == null)
        {
            errorMessage = $"未注册的标准库函数: {funcName}";
            return false;
        }
        
        // 可变参数函数：参数数量 >= 0
        if (funcInfo.IsVariadic)
        {
            return true;
        }
        
        // 固定参数函数：参数数量必须匹配
        if (argCount != funcInfo.ParameterTypes.Count)
        {
            errorMessage = $"函数 '{funcName}' 期望 {funcInfo.ParameterTypes.Count} 个参数，实际提供了 {argCount} 个";
            return false;
        }
        
        return true;
    }
    
    /// <summary>
    /// 创建默认的标准库注册表（包含所有内置函数）
    /// </summary>
    public static StandardLibraryRegistry CreateDefault()
    {
        var registry = new StandardLibraryRegistry();
        
        // ===== 输入输出函数 =====
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.CreateVariadic("输出", null)
                .WithCategory("输入输出")
                .WithDescription("输出一个或多个值到控制台")
                .WithExample("输出（\"你好世界\"）。")
                .WithDocUrl(ErrorDocumentationConfig.GetStandardLibUrl("输出"))
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("确认", "真假", "文字")
                .WithCategory("输入输出")
                .WithDescription("显示提示并等待用户输入是/否")
                .WithExample("真假 继续 是 确认（\"是否继续？\"）。")
                .WithDocUrl(ErrorDocumentationConfig.GetStandardLibUrl("确认"))
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("输入带提示", "文字", "文字")
                .WithCategory("输入输出")
                .WithDescription("显示提示信息后等待用户输入")
                .WithExample("文字 名字 是 输入带提示（\"请输入名字：\"）。")
                .WithDocUrl(ErrorDocumentationConfig.GetStandardLibUrl("输入带提示"))
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("输入带默认值", "任意", "任意")
                .WithCategory("输入输出")
                .WithDescription("如果用户直接回车则使用默认值")
                .WithExample("整型 年龄 是 输入带默认值（18）。")
                .WithDocUrl(ErrorDocumentationConfig.GetStandardLibUrl("输入带默认值"))
        );
        
        // ===== 数学函数 =====
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("绝对值", "整型", "整型")
                .WithCategory("数学")
                .WithDescription("返回整数的绝对值")
                .WithExample("整型 结果 是 绝对值（-5）。")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("最大值", "整型", "整型", "整型")
                .WithCategory("数学")
                .WithDescription("返回两个整数中的最大值")
                .WithExample("整型 最大 是 最大值（10，20）。")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("最小值", "整型", "整型", "整型")
                .WithCategory("数学")
                .WithDescription("返回两个整数中的最小值")
                .WithExample("整型 最小 是 最小值（10，20）。")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("幂", "实型", "实型", "实型")
                .WithCategory("数学")
                .WithDescription("计算底数的指数次幂")
                .WithExample("实型 结果 是 幂（2.0，3.0）。")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("平方根", "实型", "实型")
                .WithCategory("数学")
                .WithDescription("计算平方根")
                .WithExample("实型 根 是 平方根（16.0）。")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("向上取整", "整型", "实型")
                .WithCategory("数学")
                .WithDescription("向上取整")
                .WithExample("整型 结果 是 向上取整（3.14）。")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("向下取整", "整型", "实型")
                .WithCategory("数学")
                .WithDescription("向下取整")
                .WithExample("整型 结果 是 向下取整（3.14）。")
        );
        
        // ===== 字符串函数（内部使用，通过属性访问）=====
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_长度", "整型", "任意")
                .WithCategory("内部")
                .WithDescription("获取字符串或数组的长度（通过'的 长'访问）")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_反转", "任意", "任意")
                .WithCategory("内部")
                .WithDescription("反转字符串或数组（通过'的 反'访问）")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_大写", "文字", "文字")
                .WithCategory("内部")
                .WithDescription("转换为大写（通过'的 大写'访问）")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_小写", "文字", "文字")
                .WithCategory("内部")
                .WithDescription("转换为小写（通过'的 小写'访问）")
        );
        
        // ===== 数组函数（内部使用，通过属性访问）=====
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_首元素", "任意", "任意")
                .WithCategory("内部")
                .WithDescription("获取数组首元素（通过'的 首'访问）")
        );
        
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_尾元素", "任意", "任意")
                .WithCategory("内部")
                .WithDescription("获取数组尾元素（通过'的 尾'访问）")
        );
        
        // ===== 类型转换函数（内部使用）=====
        registry.RegisterFunction(
            StandardLibraryFunctionInfo.Create("内置_文字转换", "文字", "任意")
                .WithCategory("内部")
                .WithDescription("转换为文字类型")
        );
        
        return registry;
    }
}

